#include "titlebar.h"
#include "ui_titlebar.h"

#include <QHBoxLayout>
#include <QPainter>
#include <QFile>
#include <QMouseEvent>
#include <QDebug>


#define BUTTON_HEIGHT 30        // 按钮高度;
#define BUTTON_WIDTH 30         // 按钮宽度;
#define TITLE_HEIGHT 30         // 标题栏高度;

Titlebar::Titlebar(QWidget *parent) :
    QWidget(parent)
  , m_colorR(153)
  , m_colorG(153)
  , m_colorB(153)
  , m_isPressed(false)
  , m_buttonType(MIN_MAX_CLOSE_SETTING_BUTTON)
  , m_windowBorderWidth(0)
  , m_isTransparent(false)
  , ui(new Ui::Titlebar)
{
    ui->setupUi(this);
    // 初始化;
    initControl();
    initConnections();
    // 加载本地样式 MyTitle.css文件;
    loadStyleSheet(":/titlebar");
}

Titlebar::~Titlebar()
{
    delete ui;
}

void Titlebar::initControl()
{
    ui->ButtonMin->setToolTip(QStringLiteral("最小化"));
    ui->ButtonRestore->setToolTip(QStringLiteral("还原"));
    ui->ButtonMax->setToolTip(QStringLiteral("最大化"));
    ui->ButtonClose->setToolTip(QStringLiteral("关闭"));

    this->setFixedHeight(TITLE_HEIGHT);
    this->setWindowFlags(Qt::FramelessWindowHint);
}

// 信号槽的绑定;
void Titlebar::initConnections()
{
    connect(ui->ButtonMin, SIGNAL(clicked()), this, SLOT(onButtonMinClicked()));
    connect(ui->ButtonRestore, SIGNAL(clicked()), this, SLOT(onButtonRestoreClicked()));
    connect(ui->ButtonMax, SIGNAL(clicked()), this, SLOT(onButtonMaxClicked()));
    connect(ui->ButtonClose, SIGNAL(clicked()), this, SLOT(onButtonCloseClicked()));
}

// 设置标题栏背景色,在paintEvent事件中进行绘制标题栏背景色;
// 在构造函数中给了默认值，可以外部设置颜色值改变标题栏背景色;
void Titlebar::setBackgroundColor(int r, int g, int b, bool isTransparent)
{
    m_colorR = r;
    m_colorG = g;
    m_colorB = b;
    m_isTransparent = isTransparent;
    // 重新绘制（调用paintEvent事件）;
    update();
}

// 设置标题栏图标;
void Titlebar::setTitleIcon(QString filePath, QSize IconSize)
{
    QPixmap titleIcon(filePath);
    ui->TitleIcon->setPixmap(titleIcon.scaled(IconSize));
}

// 设置标题内容;
void Titlebar::setTitleContent(QString titleContent, int titleFontSize)
{
    // 设置标题字体大小;
    QFont font = ui->TitleContent->font();
    font.setPointSize(titleFontSize);
    ui->TitleContent->setFont(font);
    // 设置标题内容;
    ui->TitleContent->setText(titleContent);
    m_titleContent = titleContent;
}

// 设置标题栏长度;
void Titlebar::setTitleWidth(int width)
{
    this->setFixedWidth(width);
}

// 设置标题栏上按钮类型;
// 由于不同窗口标题栏上的按钮都不一样，所以可以自定义标题栏中的按钮;
// 这里提供了四个按钮，分别为最小化、还原、最大化、关闭按钮，如果需要其他按钮可自行添加设置;
void Titlebar::setButtonType(ButtonType buttonType)
{
    m_buttonType = buttonType;

    switch (buttonType)
    {
    case MIN_CLOSE_BUTTON:
    {
        ui->ButtonRestore->setVisible(false);
        ui->ButtonMax->setVisible(false);
    }
        break;
    case MIN_MAX_CLOSE_SETTING_BUTTON:
    {
        ui->ButtonRestore->setVisible(false);
    }
        break;
    case ONLY_CLOSE_BUTTON:
    {
        ui->ButtonMin->setVisible(false);
        ui->ButtonRestore->setVisible(false);
        ui->ButtonMax->setVisible(false);
    }
        break;
    default:
        break;
    }
}

// 设置标题栏中的标题是否会自动滚动，跑马灯的效果;
// 一般情况下标题栏中的标题内容是不滚动的，但是既然自定义就看自己需要嘛，想怎么设计就怎么搞O(∩_∩)O！
void Titlebar::setTitleRoll()
{
    connect(&m_titleRollTimer, SIGNAL(timeout()), this, SLOT(onRollTitle()));
    m_titleRollTimer.start(200);
}

// 设置窗口边框宽度;
void Titlebar::setWindowBorderWidth(int borderWidth)
{
    m_windowBorderWidth = borderWidth;
}

// 保存窗口最大化前窗口的位置以及大小;
void Titlebar::saveRestoreInfo(const QPoint point, const QSize size)
{
    m_restorePos = point;
    m_restoreSize = size;
}

// 获取窗口最大化前窗口的位置以及大小;
void Titlebar::getRestoreInfo(QPoint& point, QSize& size)
{
    point = m_restorePos;
    size = m_restoreSize;
}

// 绘制标题栏背景色;
void Titlebar::paintEvent(QPaintEvent *event)
{
    // 是否设置标题透明;
    if (!m_isTransparent)
    {
        //设置背景色;
        QPainter painter(this);
        QPainterPath pathBack;
        pathBack.setFillRule(Qt::WindingFill);
        pathBack.addRoundedRect(QRect(0, 0, this->width(), this->height()), 3, 3);
        painter.setRenderHint(QPainter::Antialiasing, true);
        painter.fillPath(pathBack, QBrush(QColor(m_colorR, m_colorG, m_colorB)));
    }

    // 当窗口最大化或者还原后，窗口长度变了，标题栏的长度应当一起改变;
    // 这里减去m_windowBorderWidth ，是因为窗口可能设置了不同宽度的边框;
    // 如果窗口有边框则需要设置m_windowBorderWidth的值，否则m_windowBorderWidth默认为0;
    if (this->width() != (this->parentWidget()->width() - m_windowBorderWidth))
    {
        this->setFixedWidth(this->parentWidget()->width() - m_windowBorderWidth);
    }
    QWidget::paintEvent(event);
}

// 双击响应事件，主要是实现双击标题栏进行最大化和最小化操作;
void Titlebar::mouseDoubleClickEvent(QMouseEvent *event)
{
    // 只有存在最大化、还原按钮时双击才有效;
    if (m_buttonType == MIN_MAX_CLOSE_SETTING_BUTTON)
    {
        // 通过最大化按钮的状态判断当前窗口是处于最大化还是原始大小状态;
        // 或者通过单独设置变量来表示当前窗口状态;
        if (ui->ButtonMax->isVisible())
            onButtonMaxClicked();
        else
            onButtonRestoreClicked();
    }

    return QWidget::mouseDoubleClickEvent(event);
}

/*
 * 以下通过mousePressEvent、mouseMoveEvent、mouseReleaseEvent
 * 三个事件实现了鼠标拖动标题栏移动窗口的效果;
 */
void Titlebar::mousePressEvent(QMouseEvent *event)
{
    if (m_buttonType == MIN_MAX_CLOSE_SETTING_BUTTON)
    {
        // 在窗口最大化时禁止拖动窗口;
        if (ui->ButtonMax->isVisible())
        {
            m_isPressed = true;
            m_startMovePos = event->globalPos();
        }
    }
    else
    {
        m_isPressed = true;
        m_startMovePos = event->globalPos();
    }

    return QWidget::mousePressEvent(event);
}

void Titlebar::mouseMoveEvent(QMouseEvent *event)
{
    if (m_isPressed)
    {
        QPoint movePoint = event->globalPos() - m_startMovePos;
        QPoint widgetPos = this->parentWidget()->pos();
        m_startMovePos = event->globalPos();
        this->parentWidget()->move(widgetPos.x() + movePoint.x(), widgetPos.y() + movePoint.y());
    }
    return QWidget::mouseMoveEvent(event);
}

void Titlebar::mouseReleaseEvent(QMouseEvent *event)
{
    m_isPressed = false;
    return QWidget::mouseReleaseEvent(event);
}

// 以下为按钮操作响应的槽;
void Titlebar::onButtonMinClicked()
{
    emit signalButtonMinClicked();
}

void Titlebar::onButtonRestoreClicked()
{
    ui->ButtonRestore->setVisible(false);
    ui->ButtonMax->setVisible(true);
    emit signalButtonRestoreClicked();
}

void Titlebar::onButtonMaxClicked()
{
    ui->ButtonMax->setVisible(false);
    ui->ButtonRestore->setVisible(true);
    emit signalButtonMaxClicked();
}

void Titlebar::onButtonCloseClicked()
{
    emit signalButtonCloseClicked();
}

// 该方法主要是让标题栏中的标题显示为滚动的效果;
void Titlebar::onRollTitle()
{
    static int nPos = 0;
    QString titleContent = m_titleContent;
    // 当截取的位置比字符串长时，从头开始;
    if (nPos > titleContent.length())
        nPos = 0;

    ui->TitleContent->setText(titleContent.mid(nPos));
    nPos++;
}

